﻿using System;
using System.Collections.Generic;
using Yoozoo.Libs;
using Yoozoo.Managers;

namespace Yoozoo.Modules.InnerCity
{
    public enum StateAction
    {
        None = 0,
        Idle = 1,
        Walk = 2,
        Patrol = 3,
        Build = 4,
        TakeObj = 5,
        Celebrate = 6,
        Collect = 7,
    }

    public class StateMachine : IClass
    {
        private List<ActionBase> actions;

        private CityUnit owner;

        private ActionBase curAction;

        public StateAction CurState
        {
            get => this.curAction == null ? StateAction.None : this.curAction.State;
        }

        public void Initialize(CityUnit owner, List<string> actionNames)
        {
            this.owner = owner;
            this.actions = new List<ActionBase>(actionNames.Count);
            foreach (var actionName in actionNames)
                AddAction(actionName)?.Init(owner);
        }
        
        public void ChangeState(StateAction state, object enterArgs = null)
        {
            if (state == this.CurState)
                return;

            foreach (var action in this.actions)
            {
                if (action.State == state)
                {
                    this.curAction?.Exit();
                    this.curAction = action;
                    this.curAction.Enter(enterArgs);
                }
            }
        }

        public void Update()
        {
            this.curAction?.Play();
        }

        public bool IsExecuteMove()
        {
            if (this.CurState == StateAction.Walk)
                return (this.curAction as WalkAction).IsExecuteMove;

            if (this.CurState == StateAction.Patrol)
                return (this.curAction as PatrolAction).IsExecuteMove;

            return false;
        }

        public void OnReset()
        {
            Dispose();
        }

        private ActionBase AddAction(string name)
        {
            switch (name)
            {
                case "IdleAction":
                    var idle = ClassManager.Get<IdleAction>();
                    this.actions.Add(idle);
                    return idle;

                case "WalkAction":
                    var walk = ClassManager.Get<WalkAction>();
                    this.actions.Add(walk);
                    return walk;

                case "PatrolAction":
                    var patrol = ClassManager.Get<PatrolAction>();
                    this.actions.Add(patrol);
                    return patrol;
                
                case "BuildAction":
                    var build = ClassManager.Get<BuildAction>();
                    this.actions.Add(build);
                    return build;

                case "TakeObjAction":
                    var takeObj = ClassManager.Get<TakeObjAction>();
                    this.actions.Add(takeObj);
                    return takeObj;

                case "CelebrateAction":
                    var celebrate = ClassManager.Get<CelebrateAction>();
                    this.actions.Add(celebrate);
                    return celebrate;
                
                case "CollectAction":
                    var collect = ClassManager.Get<CollectAction>();
                    this.actions.Add(collect);
                    return collect;
                
                default:
                    return null;
            }
        }

        private void Dispose()
        {
            this.curAction = null;
            foreach (var action in this.actions)
                ClassManager.Free(action);

            this.actions = null;
        }
    }
}